package core

import (
	"bytes"
	"fmt"
	"io"
	"errors"
	"mime"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"encoding/json"
	//"github.com/astaxie/beego"
)

func GetCommonFileByHttp(url string) (body []byte, err error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}


func DownFileByPost(url, mediaId string) (respBytes []byte, err error) {
	reqMap := make(map[string]interface{})
    reqMap["media_id"] = mediaId
    bytesData, e := json.Marshal(reqMap)
    if e != nil {
	    err = e
        return
    }
    reader := bytes.NewReader(bytesData)
    request, e := http.NewRequest("POST", url, reader)
    if e != nil {
        err = e
		return nil, err
    }
    request.Header.Set("Content-Type", "application/json;charset=UTF-8")
    client := http.Client{}
    resp, e := client.Do(request)
    if e != nil {
        err = e
		return
    }
	defer resp.Body.Close()
    respBytes, err = ioutil.ReadAll(resp.Body)
    if err != nil {
        return
    }
    return respBytes, nil
}


/*
    临时素材查询返回比较特殊
	正确情况下的返回 HTTP 头如下：
	HTTP/1.1 200 OK
	......
	Content-Type: image/jpeg 
	Content-disposition: attachment; filename="MEDIA_ID.jpg"
	......
	Content-Length: 339721
	......
	如果返回的是视频消息素材，则内容如下：
	{
	 "video_url":DOWN_URL
	}
	错误情况下的返回JSON数据包示例如下（示例为无效媒体ID错误）：
	{
	  "errcode":40007,
	  "errmsg":"invalid media_id"
	}
*/

// 文件下载API，正确返回文件，错误返回json提示信息
func GetFileByHttp(url string) (headPara map[string]string, body []byte, err error) {
	output := make(map[string]string)
	resp, err := http.Get(url)
	if err != nil {
		return output, nil, err
	}
	defer resp.Body.Close()
	disposition := resp.Header.Get("Content-Disposition")
	if disposition == "" {
	    if body, err = ioutil.ReadAll(resp.Body); err != nil {
			return output, nil, err
		}else{
		    return output, nil, errors.New(string(body))
		}
	}
	_, params, err := mime.ParseMediaType(disposition)
    if err != nil {
	   return output, nil, fmt.Errorf("ParseMediaType fail: %s", err.Error())
	}
	filename := params["filename"]
	if filename == "" {
	    return output, nil, errors.New("no filename in Content-Disposition header")
	}
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return output, nil, err
	}
	output["Disposition"] = fmt.Sprintf("attachment; filename=%s", filename)
	output["Type"] = resp.Header.Get("Content-Type")
	output["Length"] = resp.Header.Get("Content-Length")
	return output, body, nil
}

//基于文件名上传文件,fieldName是否固定为media
func PostFileByName(uri, fieldName, fileName string) (respBody []byte, err error) {
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)
	fileWriter, e := bodyWriter.CreateFormFile(fieldName, fileName)
	if e != nil {
		err = fmt.Errorf("error writing to buffer , err=%v", e)
		return
	}
	fh, e := os.Open(fileName)
	if e != nil {
		err = fmt.Errorf("error opening file , err=%v", e)
		return
	}
	defer fh.Close()
	if _, err = io.Copy(fileWriter, fh); err != nil {
		return
	}
	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()
	resp, e := http.Post(uri, contentType, bodyBuf)
	if e != nil {
		err = e
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, err
	}
	respBody, err = ioutil.ReadAll(resp.Body)
	return
}

//基于文件内容上传文件,fieldName是否固定为media
//fieldName: media
//virtualFileName: 虚拟一个文件名(需要带图像格式后缀)，比如xizang.jpg
func PostFileByData(uri, fieldName, virtualFileName string, data []byte) (respBody []byte, err error) {
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)	
	partWriter, e := bodyWriter.CreateFormFile(fieldName, virtualFileName)
	if e != nil {
		err = e
		return
	}
	if _, err = io.Copy(partWriter, bytes.NewReader(data)); err != nil {
		return
	}
	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()
	resp, e := http.Post(uri, contentType, bodyBuf)
	if e != nil {
		err = e
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, err
	}
	respBody, err = ioutil.ReadAll(resp.Body)
	return
}

//fieldName是否固定为media
func PostFileByIoReader(uri, fieldName, virtualFileName string, input io.Reader) (respBody []byte, err error) {
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)	
	partWriter, e := bodyWriter.CreateFormFile(fieldName, virtualFileName)
	if e != nil {
		err = e
		return
	}
	if _, err = io.Copy(partWriter, input); err != nil {
		return
	}
	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()
	resp, e := http.Post(uri, contentType, bodyBuf)
	if e != nil {
		err = e
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, err
	}
	respBody, err = ioutil.ReadAll(resp.Body)
	return
}

//fieldName是否固定为media
func PostFile2FormByIoReader(uri, fieldName, virtualFileName string, input io.Reader) (respBody []byte, err error) {
	var description = struct {
		Title        string `json:"title"`
		Introduction string `json:"introduction"`
	}{
		Title:        virtualFileName,
		Introduction: virtualFileName,
	}
	descriptionBytes, err := json.Marshal(&description)
	if err != nil {
		return
	}
	//
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)	
	partWriter, e := bodyWriter.CreateFormFile(fieldName, virtualFileName)
	if e != nil {
		err = e
		return
	}
	if _, err = io.Copy(partWriter, input); err != nil {
		return
	}
	//
	partWriter, e = bodyWriter.CreateFormField("description")
	if e != nil {
	    err = e
		return
	}
	if _, e = io.Copy(partWriter, bytes.NewReader(descriptionBytes)); e != nil {
		err = e
		return
	}
	//
	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()
	resp, e := http.Post(uri, contentType, bodyBuf)
	if e != nil {
		err = e
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, err
	}
	respBody, err = ioutil.ReadAll(resp.Body)
	return
}
